<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>高级代码安全分析器</title>
    <script src="https://unpkg.com/@tailwindcss/browser@4"></script>
    <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/all.min.css" rel="stylesheet">
    <style>
        body {
            font-family: 'Inter', sans-serif;
        }

        .custom-file-button {
            background-color: #dc3545;
            color: white;
            padding: 8px 16px;
            border: none;
            border-radius: 5px;
            cursor: pointer;
            transition: background-color 0.3s ease;
        }

        .custom-file-button:hover {
            background-color: #c82333;
        }

        .modal {
            display: none;
            position: fixed;
            z-index: 1;
            left: 0;
            top: 0;
            width: 100%;
            height: 100%;
            overflow: auto;
            background-color: rgba(0, 0, 0, 0.4);
        }

        .modal-content {
            background-color: #fefefe;
            margin: 10% auto;
            padding: 20px;
            border: 1px solid #888;
            width: 80%;
            max-width: 800px;
            border-radius: 5px;
            max-height: 80vh;
            overflow-y: auto;
        }

        .close {
            color: #aaa;
            float: right;
            font-size: 28px;
            font-weight: bold;
        }

        .close:hover,
        .close:focus {
            color: black;
            text-decoration: none;
            cursor: pointer;
        }

        .dropzone {
            border: 2px dashed #ccc;
            border-radius: 5px;
            padding: 20px;
            text-align: center;
            margin: 10px 0;
            transition: all 0.3s;
        }

        .dropzone.active {
            border-color: #4CAF50;
            background-color: #f0fff0;
        }

        .issue {
            padding: 10px;
            margin: 5px 0;
            border-radius: 5px;
            transition: background-color 0.3s ease;
            cursor: pointer;
        }

        .issue:hover {
            background-color: #f0f0f0;
        }

        .issue-warning {
            background-color: #fff3cd;
            color: #856404;
        }

        .issue-danger {
            background-color: #f8d7da;
            color: #721c24;
        }

        .issue-info {
            background-color: #d1ecf1;
            color: #0c5460;
        }

        .history-item {
            padding: 8px;
            margin: 4px 0;
            border-bottom: 1px solid #eee;
            cursor: pointer;
        }

        .history-item:hover {
            background-color: #f5f5f5;
        }

        .tab {
            padding: 10px 20px;
            cursor: pointer;
            border: 1px solid #ddd;
            background-color: #f1f1f1;
        }

        .tab.active {
            background-color: #fff;
            border-bottom: 2px solid #4CAF50;
        }

        .tab-content {
            display: none;
            padding: 20px;
            border: 1px solid #ddd;
            border-top: none;
        }

        .tab-content.active {
            display: block;
        }

        .advice-container {
            margin-top: 10px;
            padding: 10px;
            background-color: #f8f9fa;
            border-left: 4px solid #17a2b8;
            display: none;
        }

        .advice-title {
            font-weight: bold;
            margin-bottom: 5px;
        }

        .advice-content {
            color: #495057;
        }

        .issue-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
        }

        .issue-type {
            font-weight: bold;
            margin-right: 10px;
        }

        .issue-line {
            font-size: 0.8em;
            color: #6c757d;
        }

        header {
            text-align: center; /* 使内容居中 */
        }

        header h1 {
            margin-bottom: 0.5rem; /* 调整标题和副标题之间的间距 */
        }

        header p {
            margin-top: 0; /* 调整副标题的上边距 */
        }
    </style>
</head>

<body class="bg-gray-100 flex flex-col min-h-screen">
    <header class="bg-blue-600 text-white p-4">
        <h1 class="text-2xl font-bold">高级代码安全分析器</h1>
        <p class="text-sm">静态与动态代码安全分析，支持多种编程语言</p>
    </header>
    <main class="flex-grow p-4 md:p-8">
        <div class="bg-white p-6 rounded-lg shadow-md max-w-4xl mx-auto">
            <div class="flex border-b">
                <button id="uploadTab" class="tab active">上传分析</button>
                <button id="historyTab" class="tab">分析历史</button>
            </div>

            <div id="uploadContent" class="tab-content active">
                <h2 class="text-xl font-bold mb-4 mt-2">上传代码文件进行安全分析</h2>
                <p class="text-gray-600 mb-2">支持的文件类型：.py、.java、.c、.cpp、.js、.docx</p>
                
                <div id="dropzone" class="dropzone">
                    <i class="fas fa-cloud-upload-alt text-4xl text-gray-400 mb-2"></i>
                    <p>拖放文件到此处或</p>
                    <input type="file" id="codeFile" class="hidden" accept=".py,.java,.c,.cpp,.js,.docx">
                    <button id="customFileButton" class="custom-file-button mt-2">
                        <i class="fa-solid fa-file-upload"></i> 选择代码文件
                    </button>
                </div>
                <span id="selectedFileName" class="ml-2 text-gray-600"></span>
                
                <div class="mt-4">
                    <button id="analyzeButton"
                        class="bg-blue-600 text-white px-4 py-2 rounded hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-opacity-50">
                        <i class="fa-solid fa-magnifying-glass"></i> 分析代码
                    </button>
                </div>
            </div>

            <div id="historyContent" class="tab-content">
                <h2 class="text-xl font-bold mb-4 mt-2">分析历史记录</h2>
                <div id="historyList" class="divide-y divide-gray-200"></div>
            </div>
        </div>
    </main>
    <footer class="bg-gray-200 text-gray-600 p-4 text-center">
        &copy; 2025 高级代码安全分析器 | 支持 Python, Java, C, C++, JavaScript 和 DOCX 文件分析
    </footer>

    <!-- 分析结果模态框 -->
    <div id="resultModal" class="modal">
        <div class="modal-content">
            <span class="close">&times;</span>
            <h2 class="text-xl font-bold mb-4">分析结果</h2>
            <div id="resultDetails"></div>
            <div class="mt-4">
                <button id="exportButton" class="bg-green-600 text-white px-4 py-2 rounded hover:bg-green-700">
                    <i class="fas fa-download"></i> 导出结果
                </button>
            </div>
        </div>
    </div>

    <script>
        // DOM元素
        const analyzeButton = document.getElementById('analyzeButton');
        const codeFile = document.getElementById('codeFile');
        const customFileButton = document.getElementById('customFileButton');
        const selectedFileName = document.getElementById('selectedFileName');
        const dropzone = document.getElementById('dropzone');
        const resultModal = document.getElementById('resultModal');
        const resultDetails = document.getElementById('resultDetails');
        const closeBtn = document.querySelector('.close');
        const exportButton = document.getElementById('exportButton');
        const uploadTab = document.getElementById('uploadTab');
        const historyTab = document.getElementById('historyTab');
        const uploadContent = document.getElementById('uploadContent');
        const historyContent = document.getElementById('historyContent');
        const historyList = document.getElementById('historyList');

        // 标签页切换
        uploadTab.addEventListener('click', () => {
            uploadTab.classList.add('active');
            historyTab.classList.remove('active');
            uploadContent.classList.add('active');
            historyContent.classList.remove('active');
        });

        historyTab.addEventListener('click', () => {
            historyTab.classList.add('active');
            uploadTab.classList.remove('active');
            historyContent.classList.add('active');
            uploadContent.classList.remove('active');
            loadHistory();
        });

        // 文件选择处理
        customFileButton.addEventListener('click', () => {
            codeFile.click();
        });

        codeFile.addEventListener('change', () => {
            updateSelectedFileName();
        });

        function updateSelectedFileName() {
            const file = codeFile.files[0];
            if (file) {
                selectedFileName.textContent = `已选择文件: ${file.name}`;
            } else {
                selectedFileName.textContent = '';
            }
        }

        // 拖放区域处理
        ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
            dropzone.addEventListener(eventName, preventDefaults, false);
        });

        function preventDefaults(e) {
            e.preventDefault();
            e.stopPropagation();
        }

        ['dragenter', 'dragover'].forEach(eventName => {
            dropzone.addEventListener(eventName, highlight, false);
        });

        ['dragleave', 'drop'].forEach(eventName => {
            dropzone.addEventListener(eventName, unhighlight, false);
        });

        function highlight() {
            dropzone.classList.add('active');
        }

        function unhighlight() {
            dropzone.classList.remove('active');
        }

        dropzone.addEventListener('drop', handleDrop, false);

        function handleDrop(e) {
            const dt = e.dataTransfer;
            const files = dt.files;
            
            if (files.length > 0) {
                codeFile.files = files;
                updateSelectedFileName();
            }
        }

        // 分析按钮点击事件
        analyzeButton.addEventListener('click', async () => {
            const file = codeFile.files[0];
            if (!file) {
                alert('请选择一个代码文件');
                return;
            }

            const formData = new FormData();
            formData.append('code', file);
            formData.append('filename', file.name);

            try {
                const response = await fetch('/analyze', {
                    method: 'POST',
                    body: formData
                });
                
                if (!response.ok) {
                    throw new Error(`HTTP错误! 状态码: ${response.status}`);
                }
                
                const result = await response.json();
                showResults(file.name, result);
                
                // 如果有历史标签页，刷新历史记录
                if (historyTab.classList.contains('active')) {
                    loadHistory();
                }
            } catch (error) {
                showError(error.message);
            }
        });

        // 显示分析结果
        function showResults(filename, issues) {
            resultDetails.innerHTML = '';
            
            const h3 = document.createElement('h3');
            h3.className = 'text-lg font-bold mb-4';
            h3.textContent = `文件: ${filename} - 共发现 ${issues.length} 个问题`;
            resultDetails.appendChild(h3);
            
            if (issues.length > 0) {
                issues.forEach((issue) => {
                    const issueContainer = document.createElement('div');
                    
                    const issueDiv = document.createElement('div');
                    issueDiv.className = 'issue';
                    
                    if (issue.severity === 'danger') {
                        issueDiv.classList.add('issue-danger');
                    } else if (issue.severity === 'warning') {
                        issueDiv.classList.add('issue-warning');
                    } else {
                        issueDiv.classList.add('issue-info');
                    }
                    
                    const headerDiv = document.createElement('div');
                    headerDiv.className = 'issue-header';
                    
                    const typeDiv = document.createElement('span');
                    typeDiv.className = 'issue-type';
                    typeDiv.textContent = issue.type || '问题';
                    
                    const lineDiv = document.createElement('span');
                    lineDiv.className = 'issue-line';
                    lineDiv.textContent = issue.line ? `第 ${issue.line} 行` : '';
                    
                    headerDiv.appendChild(typeDiv);
                    headerDiv.appendChild(lineDiv);
                    
                    const descDiv = document.createElement('div');
                    descDiv.textContent = issue.description;
                    
                    issueDiv.appendChild(headerDiv);
                    issueDiv.appendChild(descDiv);
                    
                    const adviceDiv = document.createElement('div');
                    adviceDiv.className = 'advice-container';
                    
                    const adviceTitle = document.createElement('div');
                    adviceTitle.className = 'advice-title';
                    adviceTitle.textContent = '修复建议:';
                    
                    const adviceContent = document.createElement('div');
                    adviceContent.className = 'advice-content';
                    adviceContent.textContent = issue.advice || '暂无具体建议';
                    
                    adviceDiv.appendChild(adviceTitle);
                    adviceDiv.appendChild(adviceContent);
                    
                    issueDiv.addEventListener('click', () => {
                        if (adviceDiv.style.display === 'block') {
                            adviceDiv.style.display = 'none';
                        } else {
                            adviceDiv.style.display = 'block';
                        }
                    });
                    
                    issueContainer.appendChild(issueDiv);
                    issueContainer.appendChild(adviceDiv);
                    resultDetails.appendChild(issueContainer);
                });
            } else {
                const p = document.createElement('p');
                p.className = 'issue bg-green-100 text-green-700';
                p.textContent = '未发现安全问题。';
                resultDetails.appendChild(p);
            }
            
            resultModal.style.display = "block";
        }

        // 显示错误
        function showError(message) {
            resultDetails.innerHTML = '';
            
            const div = document.createElement('div');
            div.className = 'issue issue-danger';
            div.textContent = `发生错误: ${message}`;
            resultDetails.appendChild(div);
            
            resultModal.style.display = "block";
        }

        // 关闭模态框
        closeBtn.addEventListener('click', () => {
            resultModal.style.display = "none";
        });

        window.addEventListener('click', (event) => {
            if (event.target === resultModal) {
                resultModal.style.display = "none";
            }
        });

        // 导出结果
        exportButton.addEventListener('click', () => {
            let content = `安全分析报告\n文件: ${document.querySelector('#resultDetails h3').textContent}\n\n`;
            
            const issues = document.querySelectorAll('#resultDetails .issue');
            issues.forEach((issue, index) => {
                content += `问题 ${index + 1}:\n`;
                content += `${issue.textContent}\n`;
                
                const advice = issue.nextElementSibling;
                if (advice && advice.classList.contains('advice-container')) {
                    content += `${advice.textContent}\n`;
                }
                
                content += '\n';
            });
            
            const blob = new Blob([content], { type: 'text/plain' });
            const url = URL.createObjectURL(blob);
            
            const a = document.createElement('a');
            a.href = url;
            a.download = 'security_analysis_results.txt';
            document.body.appendChild(a);
            a.click();
            document.body.removeChild(a);
            URL.revokeObjectURL(url);
        });

        // 加载历史记录
        async function loadHistory() {
            try {
                const response = await fetch('/history');
                if (!response.ok) {
                    throw new Error('获取历史记录失败');
                }
                
                const history = await response.json();
                renderHistory(history);
            } catch (error) {
                historyList.innerHTML = `<div class="text-red-500">加载历史记录失败: ${error.message}</div>`;
            }
        }

        // 渲染历史记录
        function renderHistory(history) {
            historyList.innerHTML = '';
            
            if (history.length === 0) {
                historyList.innerHTML = '<div class="text-gray-500">暂无历史记录</div>';
                return;
            }
            
            history.forEach(item => {
                const div = document.createElement('div');
                div.className = 'history-item';
                
                const time = new Date(item.timestamp).toLocaleString();
                const title = document.createElement('div');
                title.className = 'font-bold';
                title.textContent = `${item.filename} - ${time}`;
                
                const count = document.createElement('div');
                count.className = 'text-sm text-gray-600';
                count.textContent = `发现问题: ${item.issue_count} 个`;
                
                div.appendChild(title);
                div.appendChild(count);
                
                div.addEventListener('click', () => {
                    showResults(item.filename, item.issues);
                });
                
                historyList.appendChild(div);
            });
        }

        // 初始化加载历史记录
        loadHistory();
    </script>
</body>

</html>